#include "relationportlist.h"

#include "uml/umlrelationalitem.h"

RelationPortList::RelationPortList()
{
    this->_sortMode = NORTH_SOUTH_SORTING;
}

RelationPortList::~RelationPortList()
{
}

QList<UmlRelation*> RelationPortList::relations()
{
    return this->_relationList;
}

QList<RelationPort*> RelationPortList::relationPorts()
{
    return this->_portList;
}

void RelationPortList::appendRelation(UmlRelation *relation, RelationPort *port)
{
    if (!this->_relationList.contains(relation)) {
        this->_relationList.append(relation);
    }

    if (!this->_portList.contains(port)) {        
        this->_portList.insert(this->insertPosition(relation), port);
    }

    this->_relationToPortDictionary[relation] = port;

    emit this->dataHasChanged();
}

void RelationPortList::removeRelation(UmlRelation *relation)
{
    RelationPort *port = this->_relationToPortDictionary[relation];

    this->_relationList.removeOne(relation);

    this->_relationToPortDictionary.remove(relation);

    if (this->_relationToPortDictionary.keys(port).isEmpty()) {

        this->_portList.removeAll(port);

        delete port;
    }

    emit this->dataHasChanged();
}

RelationPort* RelationPortList::portOfRelation(UmlRelation *relation)
{
    return this->_relationToPortDictionary[relation];
}

UmlRelation* RelationPortList::relationOfPort(RelationPort *port)
{
    return this->_relationToPortDictionary.key(port);
}

int RelationPortList::countRelations()
{
    return this->_relationList.count();
}

int RelationPortList::countPorts()
{
    return this->_portList.count();
}

int RelationPortList::countRelationsWithPort(RelationPort *port)
{
    return this->_relationToPortDictionary.keys(port).count();
}

bool RelationPortList::containsRelation(UmlRelation *relation)
{
    return this->_relationList.contains(relation);
}

void RelationPortList::setSortMode(RelationPortList::SortMode sortMode, UmlRelationalItem *relationalItem)
{
    this->_sortMode = sortMode;
    this->_relationalItem = relationalItem;
}

int RelationPortList::insertPosition(UmlRelation *relation)
{
    int insertPos = this->_portList.size();
    UmlRelationalItem *newItem = relation->item1() == this->_relationalItem ? relation->item2() : relation->item1();

    if (this->_sortMode == NORTH_SOUTH_SORTING) {
        foreach (RelationPort *port, this->_portList) {
            UmlRelation *currentRelation = this->relationOfPort(port);
            UmlRelationalItem *otherItem = currentRelation->item1() == this->_relationalItem ? currentRelation->item2() : currentRelation->item1();

            if (newItem->centerPos().x() > otherItem->centerPos().x()) {
                insertPos++;
            } else {
                break;
            }

        }
    }

    else if (this->_sortMode == WEST_EAST_SORTING) {
        foreach (RelationPort *port, this->_portList) {
            UmlRelation *currentRelation = this->relationOfPort(port);
            UmlRelationalItem *otherItem = currentRelation->item1() == this->_relationalItem ? currentRelation->item2() : currentRelation->item1();

            if (newItem->centerPos().y() > otherItem->centerPos().y()) {
                insertPos++;
            } else {
                break;
            }

        }
    }

    return insertPos;
}
